import axios from 'axios'
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
import { ElMessage, ElNotification } from 'element-plus'

// 定义通用的API响应格式
export interface ApiResponse<T = any> {
  code: number
  data: T
  message: string
}

// 创建axios实例
const service: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL || '/api', // API的基础URL
  timeout: 15000, // 请求超时时间
})

// 请求缓存Map，用于存储请求标识和对应的取消函数
const pendingRequests = new Map<string, AbortController>()
// 生成请求唯一标识
function generateRequestKey(config: InternalAxiosRequestConfig): string {
  return `${config.method}:${config.url}:${JSON.stringify(config.params)}:${JSON.stringify(config.data)}`
}

// 取消重复请求
function cancelDuplicateRequest(config: InternalAxiosRequestConfig): void {
  const requestKey = generateRequestKey(config)
  if (pendingRequests.has(requestKey)) {
    const controller = pendingRequests.get(requestKey)
    controller && controller.abort()
  }
  
  const controller = new AbortController()
  config.signal = controller.signal
  pendingRequests.set(requestKey, controller)
}

// 请求完成后移除请求记录
function removePendingRequest(config: InternalAxiosRequestConfig): void {
  const requestKey = generateRequestKey(config)
  pendingRequests.delete(requestKey)
}

// 请求拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // 取消重复请求
    cancelDuplicateRequest(config)
    
    // 添加token等认证信息
    const token = localStorage.getItem('access_token')
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    
    // 可以添加其他通用请求头
    config.headers['Content-Type'] = 'application/json'
    
    return config
  },
  (error) => {
    // 对请求错误做些什么
    console.error('Request error:', error)
    ElMessage.error('请求发送失败')
    return Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse) => {
    // 请求完成，移除记录
    removePendingRequest(response.config)
    
    // 对响应数据做点什么
    const res = response.data
    
    // 根据后端返回的状态码进行不同的处理
    if (res.code !== undefined) {
      switch (res.code) {
        case 200:
          // 成功响应
          return res
        case 401:
          // 未授权，token过期或无效
          ElNotification({
            title: '登录过期',
            message: '登录状态已过期，请重新登录',
            type: 'warning'
          })
          // 可以在这里添加跳转到登录页的逻辑
          localStorage.removeItem('access_token')
          // window.location.href = '/login'
          return Promise.reject(new Error(res.message || '登录过期'))
        case 403:
          // 拒绝访问
          ElMessage.error(res.message || '拒绝访问')
          return Promise.reject(new Error(res.message || '拒绝访问'))
        case 404:
          // 请求资源不存在
          ElMessage.error(res.message || '请求资源不存在')
          return Promise.reject(new Error(res.message || '请求资源不存在'))
        case 500:
          // 服务器内部错误
          ElMessage.error(res.message || '服务器内部错误')
          return Promise.reject(new Error(res.message || '服务器内部错误'))
        default:
          // 其他错误
          ElMessage.error(res.message || `请求失败: ${res.code}`)
          return Promise.reject(new Error(res.message || `请求失败: ${res.code}`))
      }
    } else {
      // 如果没有code字段，直接返回数据
      return res
    }
  },
  (error) => {
    // 请求完成，移除记录（即使出错也要移除）
    if (error.config) {
      removePendingRequest(error.config)
    }
    
    // 对响应错误做点什么
    console.error('Response error:', error)
    
    // 根据错误类型进行处理
    if (error.code === 'ERR_CANCELED') {
      // 请求被取消，不提示错误
      return Promise.reject(new Error('请求被取消'))
    } else if (error.code === 'ECONNABORTED') {
      // 请求超时
      ElMessage.error('请求超时，请稍后重试')
      return Promise.reject(new Error('请求超时'))
    } else if (!error.response) {
      // 网络错误
      ElMessage.error('网络错误，请检查网络连接')
      return Promise.reject(new Error('网络错误'))
    } else {
      // 其他错误
      ElMessage.error('请求失败，请稍后重试')
      return Promise.reject(error)
    }
  }
)

/**
 * GET请求
 * @param url 请求地址
 * @param params 请求参数
 * @param config 其他配置
 * @returns Promise
 */
export function get<T = any>(
  url: string,
  params?: any,
  config?: AxiosRequestConfig
): Promise<ApiResponse<T>> {
  return service({
    method: 'get',
    url,
    params,
    ...config
  })
}

/**
 * POST请求
 * @param url 请求地址
 * @param data 请求数据
 * @param config 其他配置
 * @returns Promise
 */
export function post<T = any>(
  url: string,
  data?: any,
  config?: AxiosRequestConfig
): Promise<ApiResponse<T>> {
  return service({
    method: 'post',
    url,
    data,
    ...config
  })
}

/**
 * PUT请求
 * @param url 请求地址
 * @param data 请求数据
 * @param config 其他配置
 * @returns Promise
 */
export function put<T = any>(
  url: string,
  data?: any,
  config?: AxiosRequestConfig
): Promise<ApiResponse<T>> {
  return service({
    method: 'put',
    url,
    data,
    ...config
  })
}

/**
 * DELETE请求
 * @param url 请求地址
 * @param config 其他配置
 * @returns Promise
 */
export function del<T = any>(
  url: string,
  config?: AxiosRequestConfig
): Promise<ApiResponse<T>> {
  return service({
    method: 'delete',
    url,
    ...config
  })
}

export default service